package com.atguigu.gmall.order.service.impl;



import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.cart.feign.CartFeign;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.mq.config.RabbitService;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderDetailService;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.feign.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;

/**
 * 订单接口实现类
 */
@Transactional(rollbackFor = Exception.class)
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private CartFeign cartFeign;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RabbitService rabbitService;

    /**
     * 新增订单
     *
     * @param orderInfo
     * @return
     */
    @Override
    public OrderInfo addOrder(OrderInfo orderInfo) {
        //新增订单
        orderInfo.setOrderStatus(OrderStatus.UNPAID.getComment());
        orderInfo.setCreateTime(new Date());
        orderInfo.setExpireTime(new Date(System.currentTimeMillis() + 1800*1000));
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.getComment());
        //订单写入数据库--金额为空
        orderInfoMapper.insert(orderInfo);
        //订单详情的数据
        List<CartInfo> chooseCartInfoList = cartFeign.getChooseCartInfoList(orderInfo.getUserId());
        List<OrderDetail> orderDetails = new ArrayList<>();
        BigDecimal total = new BigDecimal(0);
        for (CartInfo cartInfo : chooseCartInfoList) {
            //自己控制库存：乐观锁update
            OrderDetail orderDetail = new OrderDetail();
            //补充数据
            orderDetail.setOrderId(orderInfo.getId());
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            //获取最新的价格信息
            BigDecimal skuPrice = productFeignClient.getSkuPrice(cartInfo.getSkuId());
            total = total.add(skuPrice.multiply(new BigDecimal(cartInfo.getSkuNum())));
            orderDetail.setOrderPrice(skuPrice);
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            //修改库存
            productFeignClient.updateSkuStock(cartInfo.getSkuId(),cartInfo.getSkuNum());
            //新增详情
            orderDetailMapper.insert(orderDetail);
            orderDetails.add(orderDetail);
            //删除购物车的数据--数据库&redis
           cartFeign.delCart(orderInfo.getUserId(),cartInfo.getSkuId());
        }
        //将详细的信息保存到订单对象中去
        orderInfo.setOrderDetailList(orderDetails);
        //将价格写入订单
        orderInfo.setTotalAmount(total);
        orderInfoMapper.updateById(orderInfo);
        //发送一条延迟消息30分钟有效期，如果30分钟以后，订单的状态还是未支付，则将订单取消掉
        rabbitService.sendMessage("dead_exchange","dead_routing",
                orderInfo.getId()+"","60000");
        //返回订单信息
        return  orderInfo;
    }

    /**
     * 查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderInfo getById(Long id) {
        return orderInfoMapper.selectById(id);
    }

    /**
     * 支付成功
     *
     * @param map
     * @return
     */
    @Override
    public Integer paySuccess(Map<String, String> map) {
        //获取订单的id
        String outTradeNo = map.get("out_trade_no");
        //查询订单的信息
        OrderInfo orderInfo = orderInfoMapper.selectById(outTradeNo);
        //判断前置状态
        if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.getComment())){
            orderInfo.setOrderStatus(OrderStatus.PAID.getComment());
            orderInfo.setProcessStatus(ProcessStatus.PAID.getComment());
            String transactionId = map.get("transaction_id");
            orderInfo.setOutTradeNo(transactionId);
            orderInfo.setTradeBody(JSONObject.toJSONString(map));
            return orderInfoMapper.updateById(orderInfo);
        }

        return -1;
    }

    /**
     * 支付失败
     *
     * @param map
     * @return
     */
    @Override
    public Integer payFail(Map<String, String> map) {
        //获取订单的id
        String outTradeNo = map.get("out_trade_no");
        //查询订单的信息
        OrderInfo orderInfo = orderInfoMapper.selectById(outTradeNo);
        //判断前置状态
        if(orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.getComment())){
            orderInfo.setOrderStatus(OrderStatus.CLOSED.getComment());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.getComment());
            orderInfo.setTradeBody(JSONObject.toJSONString(map));
            return orderInfoMapper.updateById(orderInfo);
        }
        //回滚库存

        //查询订单的详情的列表获取sku和num的信息------TODO

        //回滚所有的商品的库存

        return -1;

    }

    /**
     * 取消订单
     *
     * @param orderId
     */
    @Override
    public void cancelOrder(Long orderId) {
        //查询订单的详细信息
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        //判断订单的状态，之后前置状态为：未支付的订单，修改为支付超时
        if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.getComment())){
            //修改订单的的状态
            orderInfo.setOrderStatus(OrderStatus.CLOSED.getComment());
            //修改订单的进度状态
            orderInfo.setProcessStatus(PaymentStatus.ClOSED.name());
            //数据同步到数据库中去
            orderInfoMapper.updateById(orderInfo);
            //查询订单详情
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderId));

            for (OrderDetail orderDetail : orderDetails) {
//                if (orderDetail.getSkuNum() <=  )
                //回滚库存
//                if(productFeignClient.updateSkuStock(orderDetail.getSkuId(), orderDetail.getSkuNum()) > 0){
                    productFeignClient.updateCancelSkuStock(orderDetail.getSkuId(),orderDetail.getSkuNum());
                    //删除订单详情
                    orderDetailMapper.deleteById(orderId);
            }
        }
    }


    /**
     * 生成流水号
     *
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
        //以用户id+前后缀为key
        String key = "user" + userId + ":tradeCode";
        //以随机串作为流程号
        String value = UUID.randomUUID().toString();
        //生成后保存在redis中
        stringRedisTemplate.boundValueOps(key).set(value);
        //返回流水号
        return  value;

    }

    /**
     * 比较流水号
     *
     * @param userId      获取缓存中的流水号
     * @param tradeCodeNo 页面传递过来的流水号
     * @return
     */
    @Override
    public boolean checkTradeCode(String userId, String tradeCodeNo) {
        //以用户id+前后缀为key
        String key = "user:" + userId + ":tradeCode";
        //获取已经存储的流水号信息
        String o = stringRedisTemplate.boundValueOps(key).get();
        return o.equals(tradeCodeNo);
    }

    /**
     * 删除流水号
     *
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
        //以用户id+前后缀为key
        String key = "user:" + userId + ":tradeCode";
        stringRedisTemplate.delete(key);
    }


}
